package com.rosca.converters.number2word;

import org.apache.log4j.Logger;

import java.util.Locale;

/**
 * User: vrosca
 * Date: 7/27/11
 * Time: 10:49 AM
 * &copy; PFA Rosca Val Dan Dar Ion 2011
 * <p>
 * A factory for locale-specific Number-to-word converters
 * </p>
 */
public class N2WConverterFactory {
    /**
     * Prefix and suffix to be used when computing full class name for converters
     */
    private static final String PREFIX = "com.rosca.converters.number2word.impl.", SUFFIX = "Converter";

    private static final Logger logger = Logger.getLogger(N2WConverterFactory.class);

    /**
     * @param code identifying a particular converter
     * @return the converter class
     * @throws UnsupportedLocaleException when code matches a class that is not a valid converter
     * @throws ClassNotFoundException     when no converters could be found fo the provided code
     */
    private static Class<?> getConverterClass(String code) throws UnsupportedLocaleException, ClassNotFoundException {
        Class<?> clazz = Class.forName(PREFIX + code.toUpperCase() + SUFFIX);
        if (!N2WConverter.class.isAssignableFrom(clazz))
            throw new UnsupportedLocaleException("Specified locale does not match a valid converter");
        return clazz;
    }

    /**
     * @param locale to be used for converter creation
     * @return a converter instance
     * @throws UnsupportedLocaleException when locale does not match a valid and known converter
     */
    public static N2WConverter createConverter(Locale locale) throws UnsupportedLocaleException {
        try {
            String languageCode = locale.getLanguage(), countryCode = locale.getCountry();
            logger.debug("Creating converter for locale: " + locale);
            if (languageCode.isEmpty())
                throw new UnsupportedLocaleException("Locale does not specify a language code");
            Class<?> clazz;
            try {
                clazz = getConverterClass(languageCode + countryCode); // try more specific converter first
            } catch (ClassNotFoundException e) {
                clazz = getConverterClass(languageCode); // default to base language converter second
            }
            return (N2WConverter) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            logger.debug("Creating converter failed for " + locale);
            throw new UnsupportedLocaleException("Specified locale does not match any known converters");
        } catch (Throwable t) {
            logger.debug("Creating converter failed for " + locale);
            throw new UnsupportedLocaleException(t);
        }
    }
}
